package com.example.garbage;

/**
 * @Author Shunrai
 * @create 2024/4/5 15:01
 * @Version 1.0
 * @Description
 */
import com.google.ortools.Loader;
import com.google.ortools.linearsolver.*;

public class zuihou {
    static {
        Loader.loadNativeLibraries(); // 加载OR-Tools本地库
    }
    public static void main(String[] args) {
        // 输入数据
        int numDemandPoints = 5; // 需求点数量
        int numCandidates = 10; // 候选服务站数量
        int[] demands = {10, 15, 8, 12, 20}; // 需求点的需求量
        double[][] distances = { // 需求点和候选服务站之间的距离矩阵
                {50, 60, 70, 80, 90, 100, 110, 120, 130, 140},
                {30, 40, 50, 60, 70, 80, 90, 100, 110, 120},
                {80, 90, 70, 110, 120, 130, 140, 150, 160, 170},
                {110, 120, 130, 70, 150, 160, 170, 180, 190, 200},
                {70, 80, 90, 100, 110, 120, 130, 140, 150, 160}
        };
        int[] capacities = {25, 30, 20, 35, 40, 30, 25, 35, 30, 40}; // 候选服务站的容量

        // 创建优化器
        MPSolver solver = new MPSolver("ServiceStationProblem", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING);

        // 创建决策变量
        MPVariable[][] y = new MPVariable[numDemandPoints][numCandidates];
        MPVariable[] x = new MPVariable[numCandidates];
        for (int i = 0; i < numCandidates; i++) {
            x[i] = solver.makeIntVar(0, 1, "x_" + i); // 表示服务站是否被选中
            for (int j = 0; j < numDemandPoints; j++) {
                y[j][i] = solver.makeIntVar(0, 1, "y_" + j + "_" + i); // 表示需求点是否由服务站提供服务
            }
        }

        // 创建目标函数
        MPObjective objective = solver.objective();
        for (int i = 0; i < numCandidates; i++) {
            objective.setCoefficient(x[i], 1); // 最小化服务站总数
        }
        for (int j = 0; j < numDemandPoints; j++) {
            for (int i = 0; i < numCandidates; i++) {
                objective.setCoefficient(y[j][i], distances[j][i]); // 最小化需求点和服务站之间的距离
            }
        }
        objective.setMinimization();

        // 创建约束条件
        for (int j = 0; j < numDemandPoints; j++) {
            MPConstraint demandConstraint = solver.makeConstraint(1, 1); // 每个需求点只由一个服务站提供服务
            for (int i = 0; i < numCandidates; i++) {
                demandConstraint.setCoefficient(y[j][i], 1);
            }
        }

        for (int i = 0; i < numCandidates; i++) {
            MPConstraint capacityConstraint = solver.makeConstraint(0, capacities[i]); // 服务容量约束
            for (int j = 0; j < numDemandPoints; j++) {
                capacityConstraint.setCoefficient(y[j][i], demands[j]); // 服务容量 >= 需求量总和
            }
        }

        // 服务站地点与需求点之间的距离约束
        for (int j = 0; j < numDemandPoints; j++) {
            for (int i = 0; i < numCandidates; i++) {
                if (distances[j][i] < 70) {
                    MPConstraint distanceConstraint = solver.makeConstraint(0, 1); // 0-1约束，用于限制距离小于70m
                    distanceConstraint.setCoefficient(y[j][i], 1);
                    distanceConstraint.setCoefficient(x[i],  -1);
                }
            }
        }
        // 求解问题
        MPSolver.ResultStatus resultStatus = solver.solve();

        // 检查结果是否满足距离约束
        boolean isValidSolution = true;
        for (int j = 0; j < numDemandPoints; j++) {
            for (int i = 0; i < numCandidates; i++) {
                if (distances[j][i] < 70 && y[j][i].solutionValue() > 0.5 && x[i].solutionValue() < 0.5) {
                    isValidSolution = false;
                    break;
                }
            }
        }
        // 输出结果
        if (resultStatus == MPSolver.ResultStatus.OPTIMAL ) {
            System.out.println("最优解找到！");
            System.out.println("服务站总数,距离最小值: " + objective.value());

            // 输出选择的服务站
            System.out.println("选择的服务站:");
            for (int i = 0; i < numCandidates; i++) {
                if (x[i].solutionValue() > 0.5) {
                    System.out.println("服务站 " + i + " 被选中");
                }
            }

            // 输出需求点与服务站的分配情况
            System.out.println("需求点与服务站的分配情况:");
            for (int j = 0; j < numDemandPoints; j++) {
                for (int i = 0; i < numCandidates; i++) {
                    if (y[j][i].solutionValue() > 0.5) {
                        System.out.println("需求点 " + j + " 被分配给服务站 " + i);
                    }
                }
            }
        }  else {
            System.out.println("找不到最优解或结果不满足距离约束。");
        }
    }
}